home *** CD-ROM | disk | FTP | other *** search
- /* Copyright (c) 1989 Bellcore
- * All Rights Reserved
- * Permission is granted to copy or use this program, EXCEPT that it
- * may not be sold for profit, the copyright notice must be reproduced
- * on copies, and credit should be given to Bellcore where it is due.
- * BELLCORE MAKES NO WARRANTY AND ACCEPTS NO LIABILITY FOR THIS PROGRAM.
- */
- /* $Header: line.c,v 1.3 89/05/25 07:51:36 sau Locked $
- $Source: /usr/u/sau/mgr/src/dec/RCS/line.c,v $
- */
- static char RCSid_[] = "$Source: /usr/u/sau/mgr/src/dec/RCS/line.c,v $$Revision: 1.3 $";
-
- #include "bitmap.h"
- #ifdef atarist
- #include <linea.h>
- #endif
-
- /* Draw a line - Bresenham method , portable Bitblt version (S. A. Uhler)
- */
-
- bit_line(dest, x0, y0, x1, y1, func)
- register BITMAP *dest; /* destination bitmap */
- int x0, y0, x1, y1; /* line coordinates */
- int func; /* set, clear, or invert */
- {
- register unsigned bit; /* bit offset in current word */
- register DATA *dst; /* current word in bitmap */
- register int count; /* current x position in loop */
- register int err; /* accumulated error */
- register int d_incr; /* words to next scan line */
- register int rincr, rdecr;
- int dx, dy; /* # of pixels in x and y */
- int temp;
-
- /* clip here */
-
- #ifndef NOCLIP
-
- #define TOP 001
- #define BOTTOM 002
- #define LEFT 004
- #define RIGHT 010
- #define CROSS(x,y) \
- (x<0 ? LEFT : x>= (dest->wide) ? RIGHT : 0) + \
- (y < 0 ? TOP : y >= (dest -> high) ? BOTTOM : 0)
-
- {
-
- /* The classic line clipping algorithm */
- /* (I don't remember anymore where I got it from, sorry -sau) */
-
- register int cross0 = CROSS(x0, y0);
- register int cross1 = CROSS(x1, y1);
-
- while (cross0 || cross1) {
- int cross, x, y;
- if (cross0 & cross1)
- return;
- if (cross0 != 0)
- cross = cross0;
- else
- cross = cross1;
- if (cross & (LEFT | RIGHT)) {
- int edge = (cross & LEFT) ? 0 : dest->wide - 1;
- y = y0 + (y1 - y0) * (edge - x0) / (x1 - x0);
- x = edge;
- }
- else if (cross & (TOP | BOTTOM)) {
- int edge = (cross & TOP) ? 0 : dest->high - 1;
- x = x0 + (x1 - x0) * (edge - y0) / (y1 - y0);
- y = edge;
- }
- if (cross == cross0) {
- x0 = x;
- y0 = y;
- cross0 = CROSS(x, y);
- }
- else {
- x1 = x;
- y1 = y;
- cross1 = CROSS(x, y);
- }
- }
- }
-
- /* end of clipping */
-
- #endif
-
- x0 += dest->x0;
- y0 += dest->y0;
- x1 += dest->x0;
- y1 += dest->y0;
-
- /* always draw left to right */
-
- if (x1 < x0) {
- temp = x1, x1 = x0, x0 = temp;
- temp = y1, y1 = y0, y0 = temp;
- }
- dx = x1 - x0;
- dy = y1 - y0;
-
- #ifdef INVERT
- /* invert all raster ops */
-
- func = op_invert[15&func];
- #endif
-
- #ifdef atarist
- if (IS_SCREEN(dest)) {
- __aline->_X1 = x0; __aline->_Y1 = y0;
- __aline->_X2 = x1; __aline->_Y2 = y1;
- __aline->_COLBIT0 =
- __aline->_COLBIT1 = __aline->_COLBIT1 = __aline->_COLBIT3 = 0xf;
- __aline->_LNMASK = 0xffff;
- __aline->_LSTLIN = 0xffff;
- switch(OPCODE(func)) {
- case OPCODE(SRC):
- case OPCODE(SRC | DST):
- case OPCODE(SRC | ~DST):
- case OPCODE(~0):
- __aline->_WMODE = 0;
- break;
- case OPCODE(~SRC):
- case OPCODE(~(SRC|DST)):
- case OPCODE(DST & ~SRC):
- case OPCODE(0):
- __aline->_LNMASK = 0;
- __aline->_WMODE = 0;
- break;
- case OPCODE(SRC ^ DST):
- case OPCODE(~DST):
- case OPCODE(SRC & ~DST):
- case OPCODE(~(SRC&DST)):
- __aline->_WMODE = 2;
- break;
- default:
- return;
- }
- linea3(); /* draw line on screen */
- return;
- }
- #endif
-
- d_incr = BIT_LINE(dest);
- dst = y0 * d_incr + (x0>>LOGBITS) + (dest->data);
- bit = GETLSB(MSB,(x0&BITS));
-
- if (dy <= 0)
- d_incr = -d_incr, dy = -dy;
-
- #define XMOVE if ((bit=GETLSB(bit,1))==0) {bit = MSB; dst++;}
- #define YMOVE dst += d_incr
-
- #define STEP(dx,dy,xmove,ymove,op) { \
- rincr = (dx - dy)<<1; \
- rdecr = -(dy<<1); \
- err = dx + rdecr; \
- for (count = dx; count >= 0; count--) { \
- op; \
- xmove; \
- if (err < 0) { \
- ymove; \
- err += rincr; \
- } \
- else { \
- err += rdecr; \
- } \
- } \
- }
-
- if (dx > dy) { /* gentle slope (this could be made faster) */
- switch (OPCODE(func)) {
- case OPCODE(SRC):
- case OPCODE(SRC | DST):
- case OPCODE(SRC | ~DST):
- case OPCODE(~0):
- STEP(dx, dy, XMOVE, YMOVE, *dst |= bit); /* set */
- break;
- case OPCODE(~SRC):
- case OPCODE(~(SRC|DST)):
- case OPCODE(DST & ~SRC):
- case OPCODE(0):
- STEP(dx, dy, XMOVE, YMOVE, *dst &= ~bit); /* clear */
- break;
- case OPCODE(SRC ^ DST):
- case OPCODE(~DST):
- case OPCODE(SRC & ~DST):
- case OPCODE(~(SRC&DST)):
- STEP(dx, dy, XMOVE, YMOVE, *dst ^= bit); /* invert */
- break;
- }
- }
- else { /* steep slope */
- switch (OPCODE(func)) {
- case OPCODE(SRC):
- case OPCODE(SRC | DST):
- case OPCODE(SRC | ~DST):
- case OPCODE(~0):
- STEP(dy, dx, YMOVE, XMOVE, *dst |= bit); /* set */
- break;
- case OPCODE(~SRC):
- case OPCODE(~(SRC|DST)):
- case OPCODE(DST & ~SRC):
- case OPCODE(0):
- STEP(dy, dx, YMOVE, XMOVE, *dst &= ~bit); /* clear */
- break;
- case OPCODE(SRC ^ DST):
- case OPCODE(~DST):
- case OPCODE(SRC & ~DST):
- case OPCODE(~(SRC&DST)):
- STEP(dy, dx, YMOVE, XMOVE, *dst ^= bit); /* invert */
- break;
- }
- }
- }
-